<?php
/**
 * 这个类存放一些功能单元，有数据交互的请放到model中去
 */
class CommentTool
{
    /**
     * @desc:按照字符编码截取汉字，中文按两个宽度，英文一个宽度
     */
     public static function utfSubstr($str, $position, $length,$type=1)
     {
        $startPos = strlen($str);
        $startByte = 0;
        $endPos = strlen($str);
        $count = 0;
        for($i=0; $i<strlen($str); $i++)
        {
            if($count>=$position && $startPos>$i)
            {
                $startPos = $i;
                $startByte = $count;
            }
            if(($count-$startByte) >= $length)
            {
                $endPos = $i;
                break;
            }
            $value = ord($str[$i]);
            if($value > 127)
            {
                $count++;
                if($value>=192 && $value<=223) $i++;
                elseif($value>=224 && $value<=239) $i = $i + 2;
                elseif($value>=240 && $value<=247) $i = $i + 3;
                else{
                    //logger
                }
                //else return self::raiseError("\"$str\" Not a UTF-8 compatible string", 0, __CLASS__, __METHOD__, __FILE__, __LINE__);
            }
            $count++;
        }
        if($type==1 && ($endPos-6)>$length)
        {
            return substr($str, $startPos, $endPos-$startPos)."...";
        }else{
            return substr($str, $startPos, $endPos-$startPos);
        }
    }

    /**
     * 获取第三方接口数据
     * @param $url String
     * @return Mixed
     */
    public static function fetchContent($url, $timeout = 3) {
        $info = "";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_exec($ch);
        if(!curl_errno($ch)) {
            $info = curl_multi_getcontent($ch);
        }
        curl_close($ch);
        return $info;
    }

    public static function requestUrl($url, $minLen = 5, $timeout = 3) {
        $ret = '';
        for ($i = 0; $i < 3; $i ++) {
            $ret = Utility::fetchContent($url, $timeout);
            if (strlen($ret) > $minLen) {
                break;
            }
        }
        return $ret;
    }

    public static function getUrlContents($url, $timeout=5, $header=array(), $isErrSendLog=true) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20100101 Firefox/15.0");
        curl_setopt($ch, CURLOPT_URL, $url);
        if (sizeof($header)>0)
        {
            // HOST:openbox.mobilem.360.cn
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, True);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        $content  = curl_exec($ch);
        $response = curl_getinfo( $ch );
        curl_close($ch);

        if($response['http_code'] == 200)
        {
            return $content;
        }
        else if($isErrSendLog) //默认除了日志记录接口出错的日志都远程记录日志
        {
            self::sendLog('http_curl_error', $url." ".$response['http_code']." ".curl_error($ch));
        }
        else //避免日志接口出错，导致死循环，记录日志到本地
        {
            self::writeLog('http_curl_error', $url." ".$response['http_code']." ".curl_error($ch));
        }
        return '';
    }

    public static function getPersonalConf() {
        static $ret;
        if ($ret && is_array($ret)) {
            return $ret;
        }
        if (file_exists('/data/openbox/cache_qcms/html/api/personal.conf')) {
            $ret = array();
            $fp = fopen('/data/openbox/cache_qcms/html/api/personal.conf', 'r');
            if ($fp) {
                while (($buffer = fgets($fp, 4096)) !== false) {
                    array_push($ret, trim($buffer));
                }
            }
            fclose($fp);
        }

        return $ret;
    }

    /**
     * os的合并，根据传入的os不同来做合并
     * @param  int    $os 客户端操作系统的版本号
     * @return int    合并后的版本号
     */
    public static function mergeOs($os)
    {
        $os = (int)$os;
        if ($os <= 7) {
            return 7;
        }

        if ($os >= 25) {
            return 25;
        }

        return $os;
    }

    /**
     * 初始化一个数组，用于减少foreach时的notice等等
     */
    public static function initArray(& $res)
    {
        if (empty($res) || ! is_array($res)) {
            $res = array();
        }
    }

    /**
     * @desc:使用手机安全卫士 孙洪涛 通用短链接服务的接口封装
     * @url:http://add.corp.qihoo.net/pages/viewpage.action?pageId=7209366
     * @
    */
    public static function getShortUrl($rawUrl)
    {
        $server_url = 'http://map.m.360.cn/Register';
        $src = '360assmobile';
        $passwd = 'bd541809ec9c9980249d21d6ffe46f3a';
        $url = $rawUrl;
        $token = md5("short_".$passwd.$url."_url");
        $expire = 0; //永不过期
        $data = array(
                'url' => $url,
                'src' => $src,
                'token' => $token,
                'expire' => $expire,
            );
        $rs = Helper_Http::request($server_url,'POST',$data,false,1);
        if( !empty($rs) ){
            $rs = json_decode($rs,true);
            if( $rs['retcode']==0 ){
                return $rs['short_url'];
            }
        }
        return false;
    }


    public static function mapData($data, $map) {
        $result = array();

        $data = (array)$data;

        foreach ((array)$map as $old => $new) {
            $result[$new] = isset($data[$old]) ? $data[$old] : '';
        }

        return $result;
    }

    public static function getRemainder($id, $num = 100) {
        return sprintf("%u", crc32($id)) % $num;
    }
    /**
    * @desc:判断是否是手机的浏览器访问
    */
    public static function isMobileAgent()
    {
        if(isset($_SERVER["HTTP_X_WAP_PROFILE"]))
        {
            return true;
        }


        if(preg_match("/wap\.|\.wap/i",$_SERVER["HTTP_ACCEPT"]))
        {
            return true;
        }

        if(isset($_SERVER["HTTP_USER_AGENT"]))
        {
            $user_agents = array("android", "midp", "j2me", "avantg", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows\ ce", "mmp\/", "blackberry", "mib\/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up\.b", "audio", "SIE\-", "SEC\-", "samsung", "HTC", "mot\-", "mitsu", "sagem", "sony", "alcatel", "lg", "erics", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "\d\d\di", "moto");
            foreach($user_agents as $user_string)
            {
                if(preg_match("/".$user_string."/i",$_SERVER["HTTP_USER_AGENT"]))
                {
                    return true;
                }
            }
        }

        if(preg_match("/iphone/i",$_SERVER["HTTP_USER_AGENT"]))
        {
            return false;
        }
        return false;
    }

    public static function desEncrypt($str, $key = 'zshTtp^1') {
        if (strpos($str, 'partner.iread.wo.com.cn') !== false
                || strpos($str, 'pic02.v.vnet.mobi') !== false) {
            return $str;
        }
        $o = new PHPDES($key);
        return $o->encrypt($str);
    }

    public static function desEncryptNative($str, $key = 'zshTtp^1') {     
        $o = new PHPDES($key);
        return $o->encrypt($str);
    }

    public static function desDecrypt($str, $key = 'zshTtp^1') {
        if(empty($str)){
            return $str;
        }
        $o = new PHPDES($key);
        return $o->decrypt($str);
    }

     /**
     * @desc:获取用户ip所在地区
    */
    public static function getUserIpLocaion()
    {
        if( stripos(SERVER_HOST_NAME,'zwt')!=false )
        {
            $idc = 'zwt';
        }else{
            $idc = 'bjsc';
        }
        $src = 'mobilemgr_index';
        $r = rand(1,9999);
        $ip = Helper_Http::getClientIp();     
        $sign = 'a24a7151557b91035858d164ddbe2e69';

        $guid = md5("ip=".$ip."r=".$r."src=".$src."a24a7151557b91035858d164ddbe2e69");
        $url = 'http://'.$idc.'.api.ip.360.cn?src='.$src.'&r='.$r.'&ip='.$ip.'&guid='.$guid;
        $data = Helper_Http::request($url,"GET",'','',1);
        $data = json_decode($data,true);
        return $data;
    }


    public static function vercode($ver) {
        $arr = array();
        if (substr_count($ver, '.') === 2) {
            $arr = explode('.', $ver);
            $arr[1] = str_pad(substr($arr[1], 0, 2), 2, "0", STR_PAD_LEFT);
            $arr[2] = str_pad(substr($arr[2], 0, 4), 4, "0", STR_PAD_LEFT);
            $arr[3] = '01';
        } elseif (substr_count($ver, '.') === 3) {
            $arr = explode('.', $ver);
            $arr[1] = str_pad(substr($arr[1], 0, 2), 2, "0", STR_PAD_LEFT);
            $arr[2] = str_pad(substr($arr[2], 0, 4), 4, "0", STR_PAD_LEFT);
            $arr[3] = str_pad(substr($arr[3], 0, 2), 2, "0", STR_PAD_LEFT);
        }
        return intval(join('', $arr));
    }

    /**
     * 解码混淆的手机号
     * @param  string $mobile
     * @return string
     */
    public static function decryptMobile($mobile)
    {
        $source = array('f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o');
        $dest   = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        return str_replace($source, $dest, $mobile);
    }

    /**
     * @desc   检查字符串是否为手机号,粗粒度监测
     * @param  $val string  被测的字符串
     * @return boolean
     */
    public static function checkMobile($val='')
    {
        if(preg_match('/^13[0-9]{9}$|14[0-9]{9}$|15[0-9]{9}$|17[0-9]{9}$|18[0-9]{9}$/', $val))
        {
            return True;
        }
        return False;
    }

    public static function checkM2($m2) {
        return preg_match('/^\w{32}$/', $m2);
    }


    /**
     * @desc:发送短信版本2:使用ops新提供的接口发送,原封冰清维护项目(SDK)废弃
     * @wiki:http://open.corp.qihoo.net:8360/pages/viewpage.action?pageId=23888187
     * @
    */
    public static function sendSmsV2($mobiles,$content)
    {
        if( empty($mobiles) || empty($content) )
        {
            return false;
        }

        $id = 44;
        $key = 'rgBcjVBNphW';

        if( !is_array($content) && is_array($mobiles) )  //一个内容,多个手机号
        {
            $phone = implode(',',$mobiles);
            $info[] = array(
                    'msg'   => $content,
                    'phone' => $phone,
                );
        }

        if( is_array($content) && is_array($mobiles) )   // n个内容  n个手机号 ,先只考虑一一对应 的情况
        {
            $content = array_merge($content);
            $mobiles = array_merge($mobiles);
            foreach($content as $k=>$v)
            {
                $info[$k] = array(
                        'msg' => $v,
                        'phone' => $mobiles[$k],
                    );
            }
        }

        if( !is_array($content) && !is_array($mobiles)) //一个内容,一个手机号
        {
            $info[] = array(
                    'msg'   => $content,
                    'phone' => $mobiles,
                );
        }

        $url = 'http://sms.ops.qihoo.net:8360/sms?id='.$id.'&key='.$key;
        $data['data'] = json_encode($info);
        $rs = Helper_Http::post($url, $data);
        $rs = json_decode($rs,true);

        if( isset($rs['result']) && $rs['result']==0)
        {
            return true;
        }
        $msg = json_encode($rs);
        
        //echo $rs['descriptyon'];
        return false;
    }

    /**
     * 根据qcms中的配置判断是否开启功能
     * 支持根据ip判断省份，版本，渠道号
     * 目前支持一键安装(oneinstall),切换软件游戏分类位置(switchpos)
     */
    public static function isStart($feature) {

        $vercode = $_GET['vc'];
        $ch = $_GET['ch'];

        if (file_exists('/data/openbox/cache_qcms/conf/feature_qcms_conf.json')) {
            $conf = json_decode(file_get_contents('/data/openbox/cache_qcms/conf/feature_qcms_conf.json'), true);

            if (isset($conf[$feature])) {
                $qcmsConf = $conf[$feature];

                if (isset($qcmsConf['region'])) {
                    $clientIP = Helper_Http::getClientIp();
                    //$clientIP = '11.11.11.11';
                    if (strpos($clientIP, '10.') !== 0) {
                        $regions = IP::find($clientIP);

                        if ($qcmsConf['region']['in'] && (!$regions || !in_array($regions[1], explode(',', $qcmsConf['region']['value'])))) {
                            return false;
                        } elseif (!$qcmsConf['region']['in'] && $regions && in_array($regions[1], explode(',', $qcmsConf['region']['value']))) {
                            return false;
                        }   
                    }

                }
                //print_r($qcmsConf); exit;
                if (isset($qcmsConf['vercode'])) {

                    switch ($qcmsConf['vercode']['operate']) {
                        case '>':
                            if ($vercode <= $qcmsConf['vercode']['value']) {
                                return false;
                            }
                        break;
                        case '=':
                            if ($vercode != $qcmsConf['vercode']['value']) {
                                return false;
                            }
                        break;
                        case '<':
                            if ($vercode >= $qcmsConf['vercode']['value']) {
                                return false;
                            }
                        break;
                    }

                }

                if (isset($qcmsConf['ch'])) {

                    if ($ch != $qcmsConf['ch']) {
                        return false;
                    }
                }     
            }
        }

        return true;
    }

    public static function getMillisecond(){
        list($s1,$s2)=explode(' ',microtime());
        return (float)sprintf('%.0f',(floatval($s1)+floatval($s2))*1000);
    }

    public static function getCatName($cid) {
        static $catMap = array(
            1=>'软件',
            11=>'系统输入',
            12=>'聊天通讯',
            14=>'影音图像',
            15=>'阅读学习',
            16=>'生活地图',
            18=>'壁纸主题',
            17=>'办公商务',
            13=>'网络邮件',
            2=>'游戏',
            101587=>'角色扮演',
            19=>'休闲益智',
            20=>'动作冒险',
            100451=>'网络游戏',
            51=>'体育竞速',
            52=>'飞行射击',
            53=>'经营策略',
            54=>'棋牌天地',
        );

        return $catMap[$cid];
    }

    public static function getHost() 
    {
        return (RUN_ENV == 'test') ? 'http://test1.baohe.mobilem.360.cn/' : 'http://openbox.mobilem.360.cn/';
    }

    public static function shuffle_assoc(&$array) {
        $keys = array_keys($array);
        shuffle($keys);

        foreach($keys as $key) {
            $new[$key] = $array[$key];
        }

        $array = $new;
        return true;
    }

    public static function array_orderby() {
        $args = func_get_args();
        $data = array_shift($args);
        foreach ($args as $n => $field) {
            if (is_string($field)) {
                $tmp = array();
                foreach ($data as $key => $row)
                    $tmp[$key] = $row[$field];
                $args[$n] = $tmp;
                }
        }
        $args[] = &$data;
        call_user_func_array('array_multisort', $args);
        return array_pop($args);
    }

    /**
     * @desc:处理后台ext字段中的logo512字段为160分辨率
    */
    public static function TransformationLogo512To160($logo_512)
    {
        $logo_512 = parse_url($logo_512);
        $logo_512['path'] = explode('/',$logo_512['path']);
        $logo_512['path'] = array_pop($logo_512['path']);
        $logo_url_160 = $logo_512['scheme'].'://'.$logo_512['host'].'/dr/160_160_/'.$logo_512['path'];
        return $logo_url_160;
    }

    // 输出json数据
    public static function outputJSON($data, $callback='') {
        if (!empty($callback) && preg_match('/^[a-z\._0-9]+$/i', $callback)) {
            header("Content-type: application/json");
            
            echo $callback . '(' . json_encode($data) . ')';
        } else {
            echo json_encode($data);
        }
    }

    /**
     * 从给定的JSON文件中读取目标记录
     * JSON文件内容为 {'key' : 'value'} 或者 [{'key' : 333}, {'key' : 444}]
     *
     * @param $file {string}  json文件地址 
     * @param $id {string} 数据记录key, 如果提供了$value, 则表示json内容是一个list，需遍历搜索目标记录
     * @param $value {string} list中，$key值为$value的记录
     *
     * @return {mixed}
     */
    public static function getRecordFromJSON($file, $key, $value="") {
        $content = file_get_contents($file);
        $data = json_decode($content, True);

        if (is_null($data)) {
            return NULL;
        }

        // [{},{}]
        if (!empty($value)) {
            foreach ($data as $item) {
                if (isset($item[$key]) && $item[$key] == $value) {
                    return $item;
                }
            }

            // list不存在目标数据
            return NULL;
        }

        // {a:b,c:d}
        return $data[$key];
    }

    /*
     * 判断是否为测试环境
     * 这个方法要慎用，因为测试环境未来会更改
     *
     * @return {boolean}
     */
    public static function isTestEnv() {
        $uname =  php_uname('n');
        
        return strpos($uname, 'test01v') !== False;
    }

    public static function debugLog($msg) {
        if (RUN_ENV === 'test') {
            file_put_contents(dirname(__DIR__).'../../../logs/debug.log', date('Y-m-d H:i:s')."\t".$msg."\n", FILE_APPEND);
        }
    }

    public static function sacarXss($val) {
       $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
       $search = 'abcdefghijklmnopqrstuvwxyz';
       $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
       $search .= '1234567890!@#$%^&*()';
       $search .= '~`";:?+/={}[]-_|\'\\';
       for ($i = 0; $i < strlen($search); $i++) {
          $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
          $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
       }
       $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
       $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
       $ra = array_merge($ra1, $ra2);
       $found = true; 
       while ($found == true) {
          $val_before = $val;
          for ($i = 0; $i < sizeof($ra); $i++) {
             $pattern = '/';
             for ($j = 0; $j < strlen($ra[$i]); $j++) {
                if ($j > 0) {
                   $pattern .= '(';
                   $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
                   $pattern .= '|(&#0{0,8}([9][10][13]);?)?';
                   $pattern .= ')?';
                }
                $pattern .= $ra[$i][$j];
             }
             $pattern .= '/i';
             $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2);
             $val = preg_replace($pattern, $replacement, $val);
             if ($val_before == $val) {
                $found = false;
             }
          }
       }
      return $val;
    }

    /**
     * 将日志统一记录到10.121.95.146一台服务器上，适合调试，并发量较小情景使用
     *
     */
    public static function sendLog($file, $msg) {
        if (RUN_MODE == 'test') {
            $header = array('HOST:test1.baohe.mobilem.360.cn');
        } else {
            $header = array('HOST:openbox.mobilem.360.cn');
        }
        
        $msg = base64_encode(getmypid()." ".$msg);
        $arr = array(
            'file' => $file,
            'msg' => $msg,
        );

        if (RUN_MODE == 'test') {
            $content = self::getUrlContents('http://10.121.214.10/free/log?' . http_build_query($arr), 1, $header, false); 
        } else {
            $content = self::getUrlContents('http://10.121.95.146/free/log?' . http_build_query($arr), 1, $header, false); 
        }

        return true;
    }

    public static function writeLog($file, $msg) {
        $msg = base64_decode($msg);
        file_put_contents('/home/q/server/openbox/logs/' . $file . date('Y-m') .'.log', date('Y:m:d H:i:s')."\t".$msg."\n", FILE_APPEND);
    } 

    /**
     * @desc:生成一个数字校验码
    */
    public static function getVerificationCode()
    {
        $src = substr(time(),-6,6);
        $src = $src.rand(0,99);
        $check_code = self::genVerificationCode($src);
        $code = $src.$check_code;
        return $code;
    }

    /**
     * @desc:校验一个数字校验码
    */
    public static function checkVerificationCode($code)
    {
        $code_length = strlen($code);
        if( !in_array($code_length,array(8,9)) ){
            return false;
        }
        if( !is_numeric($code) ){
            return false;
        }
        $check_time = substr($code,0,6);
        //时间不可能比某一个点小,又去来比较的时间大
        if( $check_time<176000 || $check_time>time() ){
            return false;
        }

        $check_code = substr($code,-1,1);  

        $src = substr($code,0,-1);
        $verfi_code = self::genVerificationCode($src);        
        if($check_code==$verfi_code)
        {
            return true;
        }
        return false;        
    }

    /**
     * @desc:生成最后一位数字校验码
    */
    private static function genVerificationCode($code)
    {        
        $length = strlen($code);
        $total = 0;
        for($i=0;$i<$length;$i++)
        {
            $item = $code[$i];         
            $total += $item*($i+1);        
        }
        $num = $total%10;
        return $num;
    }

    public static function logMsg($file, $type, $msg) {
        $msg = date('Y-m-d H:i:s') . "\t[{$type}]\t" . $msg . "\n";
        file_put_contents("/home/q/server/openbox/logs/{$file}" . date('Y-m-d') .'.log', $msg, FILE_APPEND);
    } 

}
